package service

import (
	"aiRole/internal/dao/model"
	"aiRole/internal/dao/query"
	"aiRole/internal/dto/request"
	result "aiRole/internal/dto/reslult"
	"aiRole/internal/dto/response"
	initSystem "aiRole/pkg/init"
	"aiRole/pkg/util"
	"bytes"
	"context"
	"encoding/json"
	"errors"
	"fmt"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
	"github.com/redis/go-redis/v9"
	"net/http"
	"regexp"
	"strconv"
	"sync"
	"time"
)

type AiService struct {
}

func (s AiService) Asr(c *gin.Context, data []byte) {
	call := util.NewAiCall()
	t := time.Now().UnixMilli()
	fileName := fmt.Sprintf("asr_%s.mp3", strconv.FormatInt(t, 10))
	err := util.UploadStream(bytes.NewReader(data), fileName, fileName)
	if err != nil {
		initSystem.Logger.Error(err.Error())
		result.Error(c, 500, "识别失败,服务器错误")
		return
	}
	url := util.GetFileUrl(fileName)
	fmt.Println(url)
	ars, err := call.CallARS(url)
	if err != nil {
		initSystem.Logger.Error(err.Error())
		result.Error(c, 500, "识别失败,服务器错误")
		return
	}
	result.Ok(c, ars)
}

// getLastMessages 查询某个会话最近 n 条消息
func getLastMessages(c *gin.Context, conversationID int64, limit int) ([]*model.ConversationMessage, error) {
	messageDB := query.Use(initSystem.DB).ConversationMessage
	list, err := messageDB.WithContext(c).
		Where(messageDB.ConversationID.Eq(conversationID)).
		Order(messageDB.CreatedAt.Desc()).
		Limit(limit).
		Find()
	if err != nil {
		initSystem.Logger.Error(err.Error())
		return nil, err
	}
	return list, nil
}
func (s AiService) Chat(c *gin.Context, req request.UserChatRequest) (string, error) {
	sessionId := req.SessionId
	// 查询最近 10 条消息
	list, err := getLastMessages(c, sessionId, 10)
	if err != nil {
		return "", errors.New("服务器错误")
	}

	// 查询会话信息
	conversationDB := query.Use(initSystem.DB).Conversation
	sessionInfo, err := conversationDB.WithContext(c).Where(conversationDB.ID.Eq(sessionId)).First()
	if err != nil {
		initSystem.Logger.Error(err.Error())
		return "", errors.New("服务器错误")
	}

	// 查询角色信息
	roleDB := query.Use(initSystem.DB).Character
	roleInfo, err := roleDB.WithContext(c).Where(roleDB.ID.Eq(sessionInfo.CharacterID)).First()
	if err != nil {
		initSystem.Logger.Error(err.Error())
		return "", errors.New("服务器错误")
	}

	text, err := json.Marshal(list)
	if err != nil {
		initSystem.Logger.Error(err.Error())
		return "", errors.New("服务器错误")
	}

	call := util.NewAiCall()
	resultText, err := call.ChatCompletion([]request.Message{
		{
			Role:    "system",
			Content: roleInfo.Prompt,
		},
		{
			Role:    "user",
			Content: fmt.Sprintf("历史会话:%s,现在的message:%s", text, req.Message),
		},
	}, "gpt-oss-120b")
	if err != nil {
		initSystem.Logger.Error(err.Error())
		return "", errors.New("服务器错误")
	}

	// 异步保存消息
	go func() {
		messages := []*model.ConversationMessage{
			{Role: "character", Content: resultText, ConversationID: sessionId},
			{Role: "user", Content: req.Message, ConversationID: sessionId},
		}
		err := query.Use(initSystem.DB).ConversationMessage.
			WithContext(c).CreateInBatches(messages, len(messages))
		if err != nil {
			initSystem.Logger.Error(err.Error())
		}
	}()

	return resultText, nil
}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	// 允许跨域访问
	CheckOrigin: func(r *http.Request) bool {
		return true
	},
}

func (s AiService) ChatV2(c *gin.Context) {
	// 升级 WebSocket
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		initSystem.Logger.Error(fmt.Sprintf("WebSocket upgrade error: %s", err.Error()))
		http.Error(c.Writer, "WebSocket upgrade failed", http.StatusInternalServerError)
		return
	}
	defer conn.Close()

	session := c.Query("sessionId")
	token := c.Query("Authorization")
	jwt, err := util.ParseJWT(token)
	if err != nil {
		initSystem.Logger.Error(err.Error())
		_ = result.WsError(conn, 401, "token无效")
		return
	}
	_, err = initSystem.RDB.Get(context.Background(), "user:"+jwt.UserId).Result()
	if errors.Is(err, redis.Nil) {
		initSystem.Logger.Error(err.Error())
		_ = result.WsError(conn, 401, "token无效")
		return
	}

	if session == "" {
		initSystem.Logger.Error("参数错误请携带sessionId")
		_ = result.WsError(conn, 401, "参数错误请携带sessionId")
		return
	}
	sessionId, err := strconv.ParseInt(session, 10, 64)
	if err != nil {
		initSystem.Logger.Error(err.Error())
		_ = result.WsError(conn, 401, "sessionId格式错误")
		return
	}

	// 查询会话和角色
	conversationDB := query.Use(initSystem.DB).Conversation
	sessionInfo, err := conversationDB.WithContext(c).Where(conversationDB.ID.Eq(sessionId)).First()
	if err != nil {
		initSystem.Logger.Error(err.Error())
		_ = result.WsError(conn, 401, "会话不存在")
		return
	}

	roleDB := query.Use(initSystem.DB).Character
	roleInfo, err := roleDB.WithContext(c).Where(roleDB.ID.Eq(sessionInfo.CharacterID)).First()
	if err != nil {
		initSystem.Logger.Error(err.Error())
		_ = result.WsError(conn, 401, "角色不存在")
		return
	}

	skillDB := query.Use(initSystem.DB).CharacterSkill

	// 创建 channel 异步写 WebSocket
	writeCh := make(chan response.WsMessage, 500)
	go func() {
		for msg := range writeCh {
			switch msg.MessageType {
			case websocket.TextMessage:
				str, ok := msg.Data.(string)
				if !ok {
					continue
				}
				_ = result.WsOk(conn, str)
			case websocket.BinaryMessage:
				data, ok := msg.Data.([]byte)
				if !ok {
					continue
				}
				_ = result.WsBinary(conn, data)
			}
		}
	}()
	// 循环读取客户端消息
	mu := sync.Mutex{}
	for {
		msgType, msgBytes, err := conn.ReadMessage()
		if err != nil {
			initSystem.Logger.Error(err.Error())
			break
		}
		var req request.UserChatRequest
		if msgType == websocket.TextMessage {
			if err := json.Unmarshal(msgBytes, &req); err != nil {
				initSystem.Logger.Error(err.Error())
				writeCh <- response.WsMessage{MessageType: websocket.TextMessage, Data: "参数错误"}
				continue
			}
		} else if msgType == websocket.BinaryMessage {
			//	语音转文字
			var key = time.Now().String()
			util.UploadStream(bytes.NewReader(msgBytes), key, key)
			aiCall := util.NewAiCall()
			url := util.GetFileUrl(key)
			fmt.Println("url:", url)
			ars, err := aiCall.CallARS(url)
			if err != nil {
				initSystem.Logger.Error(err.Error())
				writeCh <- response.WsMessage{MessageType: websocket.TextMessage, Data: "网络异常"}
				continue
			}
			fmt.Println("接收到语音消息:", ars.Data.Result.Text)
			req.Message = ars.Data.Result.Text
			if req.Message == "" {
				util.NewAiCall().WssStreamStreamV2("您没有说话，请再读一遍", "qiniu_zh_female_xyqxxj", time.Now().String(), writeCh, &mu)
				continue
			}
		}
		// 获取历史消息
		historyList, err := getLastMessages(c, sessionId, 10)
		if err != nil {
			initSystem.Logger.Error(err.Error())
			writeCh <- response.WsMessage{MessageType: websocket.TextMessage, Data: "获取历史消息失败"}
			continue
		}

		// 异步处理 AI 响应
		go func(clientMsg string, history []*model.ConversationMessage, req request.UserChatRequest) {
			historyJson, _ := json.Marshal(history)
			call := util.NewAiCall()
			aiText := ""
			// 获取技能信息
			skill, _ := skillDB.WithContext(context.TODO()).Where(skillDB.ID.Eq(req.SkillId)).First()
			skillMsg := ""
			if skill != nil {
				skillMsg = fmt.Sprintf("你拥有的技能是:%s:%s", skill.Name, skill.Prompt)
			}
			// 调用流式 AI
			err := call.ChatCompletionStream([]request.Message{
				{Role: "system", Content: roleInfo.Prompt + skillMsg},
				{Role: "user", Content: fmt.Sprintf("历史会话:%s, 当前消息:%s", historyJson, clientMsg)},
			}, "gpt-oss-120b", func(s string) {
				aiText += s
				// 推送文本流给前端
				writeCh <- response.WsMessage{MessageType: websocket.TextMessage, Data: s + "\r\n"}
				//同时触发 TTS 音频流
				//if req.Voice == 1 {
				re := regexp.MustCompile(`[^a-zA-Z\p{Han}，。！？；：“”‘’（）《》、,.!?;:"'()\s]`)
				s = re.ReplaceAllString(s, "")
				go call.WssStreamStreamV2(s, "qiniu_zh_female_xyqxxj", time.Now().String(), writeCh, &mu)
			})

			//tts, err := util.TTS(aiText, "qiniu_zh_female_tmjxxy")
			if err != nil {
				result.WsError(conn, 500, "AI 错误")
				return
			}
			//writeCh <- response.WsMessage{MessageType: websocket.TextMessage, Data: "{" + "key:" + tts + "}"}
			//if err != nil {
			//	initSystem.Logger.Error(err.Error())
			//	writeCh <- response.WsMessage{MessageType: websocket.TextMessage, Data: "AI 生成失败"}
			//	return
			//}

			// 异步保存历史消息
			go func() {
				messages := []*model.ConversationMessage{
					{Role: "user", Content: clientMsg, ConversationID: sessionId},
					{Role: "character", Content: aiText, ConversationID: sessionId},
				}
				if err := query.Use(initSystem.DB).ConversationMessage.WithContext(c).CreateInBatches(messages, len(messages)); err != nil {
					initSystem.Logger.Error(err.Error())
				}
			}()
		}(req.Message, historyList, req)
	}
}

// TTS 文本转语音/*
func (s AiService) TTS(c *gin.Context, req request.TTSRequestBody) {
	key, err := util.TTS(req.Message, req.Message)
	if err != nil {
		initSystem.Logger.Error(err.Error())
		return
	}
	result.Ok(c, key)
}
